package com.ruoyi.pack.service.impl;

import java.util.List;
import java.util.Date;
import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.common.utils.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import com.ruoyi.pack.mapper.TransportPlanMapper;
import com.ruoyi.pack.domain.TransportPlan;
import com.ruoyi.pack.service.ITransportPlanService;
import com.ruoyi.pack.domain.WayBill;
import com.ruoyi.pack.service.IWayBillService;
import com.ruoyi.pack.service.IPackLocationLogService;
import com.ruoyi.pack.domain.dto.CityTransitAnalysisDto;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * 运输计划表Service业务层处理
 *
 * @author wgs
 * @date 2025-08-16
 */
@Service
public class TransportPlanServiceImpl implements ITransportPlanService
{
    private static final Logger log = LoggerFactory.getLogger(TransportPlanServiceImpl.class);

    @Autowired
    private TransportPlanMapper transportPlanMapper;

    @Autowired
    private IWayBillService wayBillService;

    @Autowired
    private IPackLocationLogService packLocationLogService;

    /**
     * 查询运输计划表
     *
     * @param id 运输计划表主键
     * @return 运输计划表
     */
    @Override
    public TransportPlan selectTransportPlanById(Long id)
    {
        return transportPlanMapper.selectTransportPlanById(id);
    }

    /**
     * 查询运输计划表列表
     *
     * @param transportPlan 运输计划表
     * @return 运输计划表
     */
    @Override
    public List<TransportPlan> selectTransportPlanList(TransportPlan transportPlan)
    {
        return transportPlanMapper.selectTransportPlanList(transportPlan);
    }

    /**
     * 新增运输计划表
     *
     * @param transportPlan 运输计划表
     * @return 结果
     */
    @Override
    public int insertTransportPlan(TransportPlan transportPlan)
    {
        transportPlan.setCreateTime(DateUtils.getNowDate());
        return transportPlanMapper.insertTransportPlan(transportPlan);
    }

    /**
     * 修改运输计划表
     *
     * @param transportPlan 运输计划表
     * @return 结果
     */
    @Override
    public int updateTransportPlan(TransportPlan transportPlan)
    {
        transportPlan.setUpdateTime(DateUtils.getNowDate());
        return transportPlanMapper.updateTransportPlan(transportPlan);
    }

    /**
     * 根据运单ID和城市查询运输计划
     *
     * @param waybillId 运单ID
     * @param city 城市
     * @return 运输计划
     */
    @Override
    public TransportPlan selectTransportPlanByWaybillIdAndCity(Long waybillId, String city) {
        return transportPlanMapper.selectTransportPlanByWaybillIdAndCity(waybillId, city);
    }

    /**
     * 更新运输计划的到达时间和实际耗时
     *
     * @param id 运输计划ID
     * @param arrivalTime 到达时间
     * @param actualDuration 实际耗时
     * @return 结果
     */
    @Override
    public int updateArrivalTimeAndDuration(Long id, Date arrivalTime, Double actualDuration) {
        return transportPlanMapper.updateArrivalTimeAndDuration(id, arrivalTime, actualDuration);
    }

    /**
     * 更新运输计划的到达信息（包含偏差数据）
     *
     * @param id 运输计划ID
     * @param arrivalTime 到达时间
     * @param actualDuration 实际耗时
     * @param arrivalDeviation 到达偏差
     * @param deviationStatus 偏差状态
     * @return 结果
     */
    @Override
    public int updateArrivalInfoWithDeviation(Long id, Date arrivalTime, Double actualDuration,
                                             Double arrivalDeviation, String deviationStatus) {
        return transportPlanMapper.updateArrivalInfoWithDeviation(id, arrivalTime, actualDuration,
                                                                  arrivalDeviation, deviationStatus);
    }

    /**
     * 根据运单ID查询起点运输计划
     *
     * @param waybillId 运单ID
     * @return 运输计划
     */
    @Override
    public TransportPlan selectStartPointByWaybillId(Long waybillId) {
        return transportPlanMapper.selectStartPointByWaybillId(waybillId);
    }

    /**
     * 批量删除运输计划表
     *
     * @param ids 需要删除的运输计划表主键
     * @return 结果
     */
    @Override
    public int deleteTransportPlanByIds(Long[] ids)
    {
        return transportPlanMapper.deleteTransportPlanByIds(ids);
    }

    /**
     * 删除运输计划表信息
     *
     * @param id 运输计划表主键
     * @return 结果
     */
    @Override
    public int deleteTransportPlanById(Long id)
    {
        return transportPlanMapper.deleteTransportPlanById(id);
    }

    /**
     * 为运单生成运输计划
     *
     * @param wayBillId 运单ID
     * @return 结果
     */
    @Override
    @Transactional
    public int generateTransportPlanForWayBill(String wayBillId) {
        try {
            log.info("开始为运单生成运输计划，运单ID: {}", wayBillId);

            // 1. 查询运单信息
            WayBill wayBill = wayBillService.getById(wayBillId);
            if (wayBill == null) {
                log.warn("运单不存在，无法生成运输计划，运单ID: {}", wayBillId);
                return 0;
            }

            // 2. 检查是否已存在运输计划
            TransportPlan query = new TransportPlan();
            query.setWaybillId(Long.parseLong(wayBillId));
            List<TransportPlan> existingPlans = selectTransportPlanList(query);
            if (!existingPlans.isEmpty()) {
                log.info("运单已存在运输计划，跳过生成，运单ID: {}", wayBillId);
                return existingPlans.size();
            }

            // 3. 检查发货地和收货地是否完整
            if (StringUtils.isEmpty(wayBill.getAddressA()) || StringUtils.isEmpty(wayBill.getAddressB())) {
                log.warn("运单发货地或收货地城市信息不完整，无法生成运输计划，运单ID: {}", wayBillId);
                return 0;
            }

            // 4. 调用城市运输分析接口获取完整的途经城市路径
            CityTransitAnalysisDto analysisResult;
            try {
                analysisResult = packLocationLogService.analyzeCityTransit(wayBill.getSenderCity(), wayBill.getReceiverCity());
                log.info("城市运输分析完成，运单ID: {}, 途经城市数: {}", wayBillId,
                    analysisResult.getPassedCities() != null ? analysisResult.getPassedCities().size() : 0);
            } catch (Exception e) {
                log.warn("城市运输分析失败，运单ID: {}, 将使用简化方案（仅起点和终点）", wayBillId);
                // 降级处理：如果分析失败，只生成起点和终点
                return generateSimpleTransportPlan(wayBill);
            }

            // 5. 根据分析结果生成运输计划
            if (analysisResult.getPassedCities() == null || analysisResult.getPassedCities().isEmpty()) {
                log.warn("未获取到有效的途经城市数据，运单ID: {}, 使用简化方案", wayBillId);
                return generateSimpleTransportPlan(wayBill);
            }

            int totalInserted = 0;
            List<CityTransitAnalysisDto.CityPassInfo> passedCities = analysisResult.getPassedCities();

            // 6. 为每个途经城市生成运输计划记录
            for (int i = 0; i < passedCities.size(); i++) {
                CityTransitAnalysisDto.CityPassInfo cityInfo = passedCities.get(i);

                // 确定节点类型
                String nodeType = "途经点";
                if (i == 0) {
                    nodeType = "起点";
                } else if (i == passedCities.size() - 1) {
                    nodeType = "终点";
                }

                TransportPlan plan = createTransportPlan(wayBill,
                    cityInfo.getProvinceName(), cityInfo.getCityName(), "",
                    nodeType, cityInfo.getPassOrder());

                // 设置预计耗时（从起始点到该城市的时间）
                if (nodeType.equals("起点")) {
                    // 起点的实际耗时为0
                    plan.setEstimatedDuration(0.0);
                } else if (cityInfo.getAverageStayTime() != null) {
                    plan.setEstimatedDuration(cityInfo.getAverageStayTime().doubleValue());
                }

                // 设置最大耗时偏差（标准差）
                if (cityInfo.getMaxDeviation() != null) {
                    plan.setMaxDeviation(cityInfo.getMaxDeviation().doubleValue());
                    log.debug("设置{}运输计划最大耗时偏差(2σ): {} -> {} 小时", nodeType, cityInfo.getCityName(), cityInfo.getMaxDeviation());
                }

                // 设置特殊时间点
                if (nodeType.equals("起点") && wayBill.getSendTime() != null) {
                    // 起点设置为预计发货时间
                    plan.setArrivalTime(wayBill.getSendTime());
                }
                // 终点的到达时间不设置，由实际GPS定位更新

                if (insertTransportPlan(plan) > 0) {
                    totalInserted++;
                    log.debug("生成{}运输计划成功: {}, 顺序: {}", nodeType, cityInfo.getCityName(), cityInfo.getPassOrder());
                }
            }

            log.info("运单运输计划生成完成，运单ID: {}, 生成记录数: {}", wayBillId, totalInserted);
            return totalInserted;

        } catch (Exception e) {
            log.error("生成运输计划失败，运单ID: {}", wayBillId, e);
            throw new RuntimeException("生成运输计划失败: " + e.getMessage(), e);
        }
    }

    /**
     * 生成简化版运输计划（仅起点和终点）
     * 当城市运输分析失败时的降级处理方案
     */
    private int generateSimpleTransportPlan(WayBill wayBill) {
        log.info("使用简化方案生成运输计划，运单ID: {}", wayBill.getId());

        int totalInserted = 0;

        // 生成起点运输计划（发货地）
        if (StringUtils.isNotEmpty(wayBill.getAddressA())) {
            TransportPlan startPlan = createTransportPlan(wayBill,
                wayBill.getSenderProvince(), wayBill.getAddressA(), wayBill.getSenderDistrict(),
                "起点", 1);

            // 设置起点的到达时间为预计发货时间和实际耗时为0
            if (wayBill.getSendTime() != null) {
                startPlan.setArrivalTime(wayBill.getSendTime());
            }
            startPlan.setEstimatedDuration(0.0);
            startPlan.setActualDuration(0.0);
            startPlan.setMaxDeviation(0.0); // 起点没有偏差
            if (insertTransportPlan(startPlan) > 0) {
                totalInserted++;
                log.debug("生成起点运输计划成功: {}", wayBill.getSenderCity());
            }
        }

        // 生成终点运输计划（收货地）
        if (StringUtils.isNotEmpty(wayBill.getReceiverCity()) &&
            !wayBill.getReceiverCity().equals(wayBill.getSenderCity())) {

            TransportPlan endPlan = createTransportPlan(wayBill,
                wayBill.getReceiverProvince(), wayBill.getReceiverCity(), wayBill.getReceiverDistrict(),
                "终点", 2);

            // 终点的到达时间不设置，由实际GPS定位更新
            // 计算预计耗时（基于预计发货时间和预计到达时间）
            if (wayBill.getSendTime() != null && wayBill.getArriveTime() != null) {
                long diffInMillis = wayBill.getArriveTime().getTime() - wayBill.getSendTime().getTime();
                double estimatedHours = diffInMillis / (1000.0 * 60 * 60);
                endPlan.setEstimatedDuration(estimatedHours);
            }
            endPlan.setMaxDeviation(0.0); // 简化方案中没有历史数据，设置为0

            if (insertTransportPlan(endPlan) > 0) {
                totalInserted++;
                log.debug("生成终点运输计划成功: {}", wayBill.getReceiverCity());
            }
        }

        log.info("简化方案运输计划生成完成，运单ID: {}, 生成记录数: {}", wayBill.getId(), totalInserted);
        return totalInserted;
    }

    /**
     * 创建运输计划对象
     */
    private TransportPlan createTransportPlan(WayBill wayBill, String province, String city, String district,
                                              String nodeType, int passOrder) {
        TransportPlan plan = new TransportPlan();
        plan.setWaybillId(Long.parseLong(wayBill.getId()));
        plan.setBillNo(wayBill.getBillNo());
        plan.setLocatorId(wayBill.getLocatorId());
        plan.setLocatorCode(wayBill.getLocatorCode());
        plan.setProvince(province);
        plan.setCity(city);
        plan.setDistrict(district);
        plan.setNodeType(nodeType);
        plan.setPassOrder(passOrder);

        return plan;
    }
}
